﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Atmk.WaterMeter.MIS.Commons;
using Atmk.WaterMeter.MIS.Commons.Interfaces;
using Atmk.WaterMeter.MIS.Commons.Interfaces.GateWay;
using Atmk.WaterMeter.MIS.Commons.Interfaces.Logic;
using Atmk.WaterMeter.MIS.Commons.Interfaces.Logic.Statistics;
using Atmk.WaterMeter.MIS.Commons.Utils;
using Atmk.WaterMeter.MIS.Commons.ViewModels.ReadMeter;
using Atmk.WaterMeter.MIS.Entities;
using Atmk.WaterMeter.MIS.Entities.Enums;
using Atmk.WaterMeter.MIS.Entities.Models;
using NLog;

namespace Atmk.WaterMeter.MIS.Logic
{
    /// <summary>
    ///     水表系统指令逻辑
    /// </summary>
    public class MeterCommandsLogic : IMeterCommandsLogic
    {
        private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
        private readonly IBaseInfoLogic _baseInfoLogic;
        private readonly ICommandSender _commandSender;
        private readonly IRepository _repository;
        private readonly ICT_NBIoT_CommandSenderHelper _ctNbioTCommandSenderHelper;

        public MeterCommandsLogic(
            IRepository repository,
            IBaseInfoLogic baseInfoLogic,
            ICommandSender commandSender,
            ICT_NBIoT_CommandSenderHelper ctNbioTCommandSenderHelper
        )
        {
            _ctNbioTCommandSenderHelper = ctNbioTCommandSenderHelper;
            _repository = repository;
            _baseInfoLogic = baseInfoLogic;
            _commandSender = commandSender;
        }
        List<District> newDistrict = new List<District>();
        /// <summary>
        ///     判断是否与未发送指令重复
        /// </summary>
        /// <param name="meterNumber"></param>
        /// <param name="command"></param>
        /// <returns></returns>
        public bool SameCommand(string meterNumber, int TapValue)
        {
            using (var _context = Datas.ContextBuilder.Build())
            {
                ////判断指令24小时重复
                //var hasmc=_context.MeterCommand.Where(m => m.MeterNumber == meterNumber).OrderByDescending(m=>m.CreateTime).FirstOrDefault(m=>m.CommandStatus== TapValue);
                //if (hasmc==null)
                //{
                //    return false;
                //}
                var mc = new MeterCommand()
                {
                    Command = TapValue == 1 ? "开阀" : "关阀",
                    CreateTime = DateTime.Now,
                    MeterNumber = meterNumber,
                    CommandStatus = TapValue,
                    ExecuteTime=DateTime.Now
                };
                _context.MeterCommand.Add(mc);
                return _context.SaveChanges() > 0;
            }
        }

        /// <summary>
        /// 设置开关阀指令
        /// </summary>
        /// <param name="meterNumber"></param>
        /// <param name="replace">是否替换原指令</param>
        /// <param name="commandType"></param>
        /// <returns></returns>
        public bool SetValveCommand(string CTdeviceId, int CommandTapValue)
        {
            #region MyRegion
            //var name = Enum.GetName(typeof(CommandType), commandType);
            ////如果可替换--开关阀的
            //var commands = _repository.FindAll<MeterCommand>().Where(m =>
            //        m.CommandStatus == (int)CommandStatus.未发送 && m.MeterNumber == meterNumber)
            //    .ToList();
            //var otherType = CommandType.开阀指令;
            //if (commandType == CommandType.开阀指令)
            //    otherType = CommandType.关阀指令;
            ////判断不同操作有无记录
            //commands = commands.Where(c => c.Command == otherType.ToString()).ToList();
            //if (commands.Count > 0)
            //{
            //    if (replace)
            //    {
            //        var com = commands.First();
            //        com.Command = commandType.ToString();
            //        if (_repository.Update(com) > 0) return true; //仅修改未发送列表里的阀门控制指令即可，不用添加发送指令的方法里
            //        _logger.Error("修改指令失败");
            //        return false;
            //    }
            //    _logger.Warn($"已有该水表的{commandType.ToString()}");
            //    return false;
            //}
            //var command = new MeterCommand
            //{
            //    MeterNumber = meterNumber,
            //    Command = name
            //};

            //var run = _commandSender.Send(ref command, commandType);
            //command.CommandStatus = (int)run;
            //if (_repository.Add(command) > 0) return true;
            //_logger.Error("添加指令失败");
            //return false;
            //执行命令并获取指令Id 
            #endregion
            var res = _ctNbioTCommandSenderHelper.SendTapCommand(CTdeviceId, CommandTapValue);
            //反馈数据包括指令Id
            //var nbCommandId = res.commandId;
            ////memo赋值
            //var nBmemo = new CommandMemoEntity
            //{
            //    CommandRefId = nbCommandId
            //};
            //commands.Memo = JsonConvert.SerializeObject(nBmemo);
            var status = res.status;
            if (status== "PENDING")
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        ///     设置抄表指令
        /// </summary>
        /// <param name="meterNumber"></param>
        /// <param name="commandType"></param>
        /// <returns></returns>
        public bool SetReadCommand(string meterNumber, CommandType commandType)
        {
            try
            {
                var name = Enum.GetName(typeof(CommandType), commandType);
                _logger.Info("开始设置抄表指令");
                var command = new MeterCommand
                {
                    MeterNumber = meterNumber,
                    Command = name
                };
                var run = _commandSender.Send(ref command, commandType);
                command.CommandStatus = (int)run;
                if (_repository.Add(command) > 0) return true;
                _logger.Error("添加指令失败");
                return false;
            }
            catch (Exception e)
            {
                _logger.Error(e);
                return false;
            }
        }

        /// <summary>
        ///     撤销水表指令
        /// </summary>
        /// <param name="cid"></param>
        /// <returns></returns>
        public bool DeleteCommand(string cid)
        {
            try
            {
                var command = _repository.FindById<MeterCommand>(cid);
                command.CommandStatus = (int)CommandStatus.撤销;
                if (_repository.Update(command) > 0) return true;
            }
            catch (Exception e)
            {
                _logger.Error(e);
                return false;
            }

            return false;
        }

        /// <summary>
        /// 查询水表信息
        /// </summary>
        /// <param name="aid"></param>
        /// <param name="page"></param>
        /// <param name="staffId"></param>
        /// <param name="searchType"></param>
        /// <param name="searchValue"></param>
        /// <returns></returns>
        public object GetMeters(string aid, int page, string staffId, string Projectsid, string searchType = "", string searchValue = "")
        {
            try
            {
                //获取配置
                var pageSize = _baseInfoLogic.PageSize(staffId);
                using (var _context = Datas.ContextBuilder.Build())
                {
                    //var total_districts = _context.District.Where(m => m.Id.ToString() == aid).ToList();
                    var total_districts = _context.District.ToList();
                    //var Projects2district = context.District.Where(m => m.ProjectId == Projectsid).ToList();
                    //getNodeNext(Projects2district, aid, Projects2district);
                    //var districts_ids = newDistrict.Select(m1 => m1.Id.ToString());
                    List<Owner> total_owners = null;
                    List<Meter> total_meters = null;
                    string[] ownerids = null;
                    switch (searchType)
                    {
                        case "业主姓名":
                            total_owners = _context.Owner.Where(m => m.Name.Contains(searchValue)).ToList();
                            ownerids = total_owners.Select(m1 => m1.Id).ToArray();
                            total_meters = _context.Meter.Where(m => ownerids.Contains(m.OwnerId)).ToList();
                            break;
                        case "手机号码":
                            total_owners = _context.Owner.Where(m => m.Mobile.Contains(searchValue)).ToList();
                            ownerids = total_owners.Select(m1 => m1.Id).ToArray();
                            total_meters = _context.Meter.Where(m => ownerids.Contains(m.OwnerId)).ToList();
                            break;
                        case "表编号":
                            total_meters = _context.Meter.Where(m => m.MeterNumber.Contains(searchValue)).ToList();
                            ownerids =total_meters.Select(m => m.OwnerId).ToArray();
                            total_owners = _context.Owner.Where(m => ownerids.Contains(m.Id)).ToList();
                            break;
                        default:
                            total_owners = _context.Owner.Where(m => m.DistrictId == aid).ToList();
                            total_meters = _context.Meter.Where(m => m.MeterState == "建档" && m.DistrictId == aid).ToList();
                            break;
                    }
                    //拼接

                    var templist = total_meters.Skip((page - 1) * pageSize).Take(pageSize).ToList();
                    var lists = new object[templist.Count];
                    var CTdeviceids = templist.Select(m1 => m1.CtdeviceId);
                    var meterReads = _context.MeterReadingRecord.Where(m => CTdeviceids.Contains(m.CtdeviceId)).GroupBy(m => m.CtdeviceId).Select(m => m.OrderByDescending(m1 => m1.ReadTime));

                    for (var i = 0; i < templist.Count(); i++)
                    {
                        var owner = total_owners.FirstOrDefault(o => templist[i].OwnerId == o.Id.ToString());
                        var district = total_districts.FirstOrDefault(o => templist[i].DistrictId == o.Id.ToString());
                        var meterReadings = meterReads.FirstOrDefault(r => r.First().CtdeviceId == templist[i].CtdeviceId);
                        if (owner == null)
                            continue;
                        string tapState="", meterValue = "", readTime = "";
                        if (meterReadings != null)
                        {
                            var meterReadingEntity = meterReadings.Select(m => m).FirstOrDefault();
                            if (meterReadingEntity != null)
                            {
                                tapState = PublicSwitch.ValveType(meterReadingEntity.ValveState); //阀门状态
                                meterValue = meterReadingEntity.Value.ToString();                         //水表最新值
                                readTime = meterReadingEntity.ReadTime.ToString("yyyy-MM-dd HH:mm"); //抄表时间   
                            }
                        }

                        lists[i] = new
                        {
                            districtName = district.Name,
                            ownerId = owner?.Id,                                          //业主Id                
                            ownerName = owner?.Name,                             //业主姓名
                            houseNumber = owner.HouseNumber,               //门牌号           
                            mobile = owner.Mobile,                                      //手机号码
                            meterId = templist[i].Id,                                        //水表Id
                            CTdeviceid= templist[i].CtdeviceId,
                            meterType = templist[i].MeterType,                       //表类型
                            meterNumber = templist[i].MeterNumber,            //表编号
                            tapState,
                            meterValue,
                            readTime
                        };
                    }
                    //获取分页数据
                    //var list = PaginatedList<object>.Create(, page, pageSize);
                    var data = new
                    {
                        total = total_meters.Count,
                        pageSize,
                        list=lists
                    };
                    return data;
                }
            }
            catch (Exception e)
            {
                _logger.Error(e);
                throw new Exception("查询水表信息错误", e);
            }
        }

        public void getNodeNext(List<District> districts, string id, List<District> districtsOld)
        {

            if (districts.Any(m => m.Id.ToString() == id && m.NodeType == (int)TreeNodeType.last))
            {
                newDistrict.AddRange(districts.Where(m => m.Id.ToString() == id));
            }
            else
            {     
                foreach (var item in districtsOld.Where(m => m.Parent == id))
                {
                    getNodeNext(districtsOld.Where(m => m.Parent == id).ToList(), item.Id.ToString(), districtsOld);
                }
            }
        }

        /// <summary>
        ///     查询所有水表命令
        /// </summary>
        /// <returns></returns>
        public object GetCommand(string meterNumber, int page,string userid)
        {
            try
            {
                var pageSize = _baseInfoLogic.PageSize(userid);
                using (var _context = Datas.ContextBuilder.Build())
                {
                    var lists = _context.MeterCommand.Where(m => m.MeterNumber == meterNumber).OrderByDescending(m => m.CreateTime).Select(m=>new MeterCommand { 
                        MeterNumber=m.MeterNumber,
                        Memo = m.CreateTime.ToString("yyyy-MM-dd HH:mm"),
                        Command=m.Command
                    }).ToList();
                    //获取分页数据
                    var list = PaginatedList<MeterCommand>.Create(lists, page, pageSize);
                    var data = new
                    {
                        total = lists.Count(),
                        pageSize,
                        list
                    };
                    return data;
                }
            }
            catch (Exception e)
            {
                _logger.Error(e);
                throw new Exception(e.Message, e);
            }
        }

        private List<MeterCommand> GetCommandses(string meterNumber, CommandType command)
        {
            var name = Enum.GetName(typeof(CommandType), command);
            var commands = _repository.FindAll<MeterCommand>().Where(m =>
                m.Command.Contains(name) && m.CommandStatus == (int)CommandStatus.未发送 &&
                m.MeterNumber == meterNumber.ToString()).ToList();
            return commands;
        }
    }
}